package com.rp.dao.remote;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import com.rp.dao.IEstabelecimentoDAO;
import com.rp.dao.ResultSetProcessor;
import com.rp.model.Estabelecimento;

public class EstabelecimentoDAO extends AbstractDB implements
	IEstabelecimentoDAO {

    private static EstabelecimentoDAO INSTANCE;

    private EstabelecimentoDAO() {
    }

    public static EstabelecimentoDAO get() {
	if (INSTANCE == null) {
	    INSTANCE = new EstabelecimentoDAO();
	}
	return INSTANCE;
    }

    @Override
    public long buscarCnpjPorNome(String nome) throws Throwable {
	Statement preparedStatement = ConnectionFactory.get().createStatement();
	try {
	    ResultSet rs = preparedStatement
		    .executeQuery("SELECT cnpj FROM estabelecimento WHERE nome = '"
			    + nome + "';");
	    try {
		if (rs.next()) {
		    long cnpj = rs.getLong("cnpj");
		    return cnpj;
		}
	    } finally {
		rs.close();
	    }
	} finally {
	    preparedStatement.close();
	}
	return -1;
    }

    @Override
    public List<String> buscarEstabelecimentos() throws Throwable {
	List<String> nomes = new ArrayList<String>();
	Statement preparedStatement = ConnectionFactory.get().createStatement();
	try {
	    ResultSet rs = preparedStatement
		    .executeQuery("SELECT nome FROM estabelecimento;");
	    try {
		while (rs.next()) {
		    String nome = rs.getString(1);
		    nomes.add(nome);
		}
	    } finally {
		rs.close();
	    }
	} finally {
	    preparedStatement.close();
	}
	return nomes;
    }

    @Override
    public Estabelecimento buscarPeloCnpj(long cnpj) throws Throwable {
	Estabelecimento estabelecimento = null;
	Statement preparedStatement = ConnectionFactory.get().createStatement();
	try {
	    ResultSet rs = preparedStatement
		    .executeQuery("SELECT * FROM estabelecimento WHERE CNPJ = "
			    + cnpj + ";");
	    try {
		while (rs.next()) {
		    estabelecimento = getEstabelecimento(rs);
		}
	    } finally {
		rs.close();
	    }
	} finally {
	    preparedStatement.close();
	}
	return estabelecimento;
    }

    Estabelecimento getEstabelecimento(ResultSet rs) throws SQLException {
	final String nome = rs.getString("nome");
	final long cnpj = rs.getInt("cnpj");
	final long latitude = rs.getLong("latitude");
	final long longitude = rs.getLong("longitude");
	final String endereco = rs.getString("endereco");
	final Timestamp data = rs.getTimestamp("data_alteracao");
	return new Estabelecimento(nome, cnpj, endereco, latitude, longitude,
		data.getTime());
    }

    @Override
    public void insereEstabelecimento(Estabelecimento estabelecimento)
	    throws Throwable {
	String nome = estabelecimento.getNome();
	long cnpj = estabelecimento.getCnpj();
	long latitude = estabelecimento.getLatitude();
	long longitude = estabelecimento.getLongitude();
	String endereco = estabelecimento.getEndereco();
	long dataAlteracao = estabelecimento.getDataAlteracao();
	Statement preparedStatement = ConnectionFactory.get().createStatement();
	try {
	    preparedStatement
		    .executeUpdate("INSERT INTO estabelecimento (nome,cnpj,latitude,longitude,endereco, data_alteracao) VALUES('"
			    + nome
			    + "',"
			    + cnpj
			    + ","
			    + latitude
			    + ","
			    + longitude
			    + ",'"
			    + endereco
			    + "','"
			    + new Timestamp(dataAlteracao).toString() + "');");
	} finally {
	    preparedStatement.close();
	}
    }

    @Override
    public void atualizaEstabelecimento(Estabelecimento estabelecimento)
	    throws Throwable {
	String nome = estabelecimento.getNome();
	long cnpj = estabelecimento.getCnpj();
	long latitude = estabelecimento.getLatitude();
	long longitude = estabelecimento.getLongitude();
	String endereco = estabelecimento.getEndereco();
	long dataAlteracao = estabelecimento.getDataAlteracao();
	Statement preparedStatement = ConnectionFactory.get().createStatement();
	try {
	    preparedStatement
		    .executeUpdate("UPDATE estabelecimento SET nome = '" + nome
			    + "', latitude = " + latitude + ", longitude = "
			    + longitude + ", endereco = '" + endereco
			    + "', data_alteracao = '"
			    + new Timestamp(dataAlteracao).toString()
			    + "' WHERE cnpj = " + cnpj);
	} finally {
	    preparedStatement.close();
	}
    }

    public ResultSetProcessor<Estabelecimento> getPendentes(Calendar data)
	    throws Throwable {
	final Statement preparedStatement = ConnectionFactory.get()
		.createStatement();
	final ResultSet rs = preparedStatement
		.executeQuery("SELECT * FROM estabelecimento WHERE data_alteracao > '"
			+ new Timestamp(data.getTimeInMillis()).toString()
			+ "';");
	return new ResultSetProcessor<Estabelecimento>() {
	    @Override
	    public Estabelecimento process() throws Throwable {
		if (rs.next()) {
		    return getEstabelecimento(rs);
		}
		rs.close();
		preparedStatement.close();
		return null;
	    }
	};
    }

    public long count(Calendar data) throws Throwable {
	preparedStatement = ConnectionFactory.get().createStatement();
	resultSet = preparedStatement
		.executeQuery("SELECT count(*) FROM estabelecimento WHERE data_alteracao > '"
			+ new Timestamp(data.getTimeInMillis()).toString()
			+ "';");
	if (resultSet.next()) {
	    int count = resultSet.getInt(1);
	    return count;
	}
	return 0;
    }

}
